package com.gnuc.thoth.service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.List;
import java.util.TimeZone;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteConstraintException;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.ContactsContract.PhoneLookup;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;

import com.gnuc.thoth.R;
import com.gnuc.thoth.app.SetupMain;
import com.gnuc.thoth.app.TabMain;
import com.gnuc.thoth.app.screens.SyncMain;
import com.gnuc.thoth.framework.Thoth;
import com.gnuc.thoth.framework.ThothLog;
import com.gnuc.thoth.framework.auth.ThothAuth;
import com.gnuc.thoth.framework.callbacks.ThothAccountCallback;
import com.gnuc.thoth.framework.callbacks.ThothRequestCallback;
import com.gnuc.thoth.framework.db.ThothDB;
import com.gnuc.thoth.framework.network.NetworkStatistics;
import com.gnuc.thoth.framework.utils.MD5;
import com.gnuc.thoth.service.listeners.RequestListener;

/**
 * ThothService is the service component of Thoth Application.<br/>
 * The service is responsible for performing following activities in the background.
 * <ul>
 * <li>Submit AppTable data to Web-service</li>
 * <li>Submit AppTable data to Google Calendar (if activated)</li>
 * </ul>
 * 
 * @author GNUC
 * @version 1.0
 */
public class ThothService extends IntentService
{
	static Context				cx				= null;
	int							pbMax			= 1;
	int							pbProgress	= 0;
	static ExecutorService	service		= null;
	
	public ThothService()
	{
		super("Thoth Service");
	}
	
	@Override
	public void onStart(Intent intent, int startId)
	{
		super.onStart(intent, startId);
		service = Executors.newSingleThreadExecutor();
	}
	
	public void connectToThothServer()
	{
		RequestListener.onReceive(Thoth.REQ.CONNECT, new ThothRequestCallback()
		{
			@Override
			public void progress(int resultCode, int progressValue, final int r)
			{}
			
			@Override
			public void handle(int resultCode)
			{
				if (resultCode == 1)
					updateLogs();
				else if (resultCode == -1)
					sHandler.sendEmptyMessage(-1);
			}
		});
	}
	
	public void updateLogs()
	{
		pbMax = pbProgress = 0;
		final NotificationManager nfm = (NotificationManager) cx.getSystemService(Context.NOTIFICATION_SERVICE);
		final Notification nf = new Notification(Thoth.APP, "Thoth: Server update", System.currentTimeMillis());
		nf.ledARGB = android.graphics.Color.BLUE;
		nf.ledOnMS = 300;
		nf.ledOffMS = 100;
		nf.flags |= Notification.FLAG_NO_CLEAR + Notification.FLAG_SHOW_LIGHTS;
		RemoteViews contentView = new RemoteViews(cx.getPackageName(), R.layout.notify_nwk_update);
		contentView.setProgressBar(R.id.no_nw_up_pb, pbMax, pbProgress, false);
		contentView.setTextViewText(R.id.no_nw_up_status, "Log Update....");
		nf.contentView = contentView;
		Intent defaultIntent = new Intent();
		defaultIntent.setAction("Default");
		nf.contentIntent = PendingIntent.getActivity(cx, 0, null, 0);
		nf.contentView.setProgressBar(R.id.no_nw_up_pb, 1, 0, false);
		nfm.notify(Thoth.APP + 2, nf);
		RequestListener.onReceive(Thoth.REQ.LOG_CREATE, new ThothRequestCallback()
		{
			@Override
			public void handle(int resultCode)
			{
				Thoth.clearNotifications();
				if (resultCode == -1)
				{
					// Thoth.showUpdateFailNotification();
					sHandler.sendEmptyMessage(-1);
				}
				else if (resultCode == 4)
					sHandler.sendEmptyMessage(2);
				updateStatistics();
			}
			
			@Override
			public void progress(int resultCode, int progressValue, int reference)
			{
				if (resultCode == -50)
				{
					pbMax += progressValue;
					nf.contentView.setProgressBar(R.id.no_nw_up_pb, pbMax, 0, false);
					nfm.notify(Thoth.APP + 2, nf);
				}
				else
				{
					pbProgress += progressValue;
					nf.contentView.setProgressBar(R.id.no_nw_up_pb, pbMax, pbProgress, false);
					nfm.notify(Thoth.APP + 2, nf);
				}
			}
		});
	}
	
	public void updateStatistics()
	{
		pbMax = pbProgress = 0;
		final NotificationManager nfm = (NotificationManager) cx.getSystemService(Context.NOTIFICATION_SERVICE);
		final Notification nf = new Notification(Thoth.APP, "Thoth: Statistics update", System.currentTimeMillis());
		nf.ledARGB = android.graphics.Color.YELLOW;
		nf.ledOnMS = 300;
		nf.ledOffMS = 100;
		nf.flags |= Notification.FLAG_NO_CLEAR + Notification.FLAG_SHOW_LIGHTS;
		RemoteViews contentView = new RemoteViews(cx.getPackageName(), R.layout.notify_nwk_update);
		contentView.setProgressBar(R.id.no_nw_up_pb, pbMax, pbProgress, false);
		contentView.setTextViewText(R.id.no_nw_up_status, "Statistics Update....");
		nf.contentView = contentView;
		Intent defaultIntent = new Intent();
		defaultIntent.setAction("Default");
		nf.contentIntent = PendingIntent.getActivity(cx, 0, null, 0);
		nf.contentView.setProgressBar(R.id.no_nw_up_pb, 1, 0, false);
		nfm.notify(Thoth.APP + 2, nf);
		Thoth.Settings.APP_STATS_UPDATE = true;
		Thoth.Settings.write();
		ThothLog.i("REQ.LOG_ANALYTICS is in progress.");
		RequestListener.onReceive(Thoth.REQ.LOG_ANALYTICS, new ThothRequestCallback()
		{
			@Override
			public void handle(int resultCode)
			{
				Thoth.clearNotifications();
				if (resultCode == 1)
					sHandler.sendEmptyMessage(1);
				else
				{
					// Thoth.showStatUpdateFailNotification();
					sHandler.sendEmptyMessage(-1);
				}
			}
			
			@Override
			public void progress(int resultCode, int progressValue, int reference)
			{
				if (resultCode == -50)
				{
					pbMax += progressValue;
					nf.contentView.setProgressBar(R.id.no_nw_up_pb, pbMax, 0, false);
					nfm.notify(Thoth.APP + 2, nf);
				}
				else
				{
					pbProgress += progressValue;
					nf.contentView.setProgressBar(R.id.no_nw_up_pb, pbMax, pbProgress, false);
					nfm.notify(Thoth.APP + 2, nf);
				}
			}
		});
	}
	
	public static void updateGoogleCalendar(final long time, final long duration, final String title, final String description)
	{
		if (Thoth.Settings.USR_DEVICE_ACCOUNT_CALENDAR > 0)
		{
			final Uri CALENDAR = (Integer.parseInt(Build.VERSION.SDK) > Build.VERSION_CODES.ECLAIR_MR1) ? Uri.parse("content://com.android.calendar") : Uri.parse("content://calendar");
			final ContentResolver cr = cx.getContentResolver();
			final ContentValues event = new ContentValues();
			Thoth.Settings.read();
			event.put("calendar_id", Thoth.Settings.USR_DEVICE_ACCOUNT_CALENDAR);
			event.put("title", title);
			event.put("description", description);
			event.put("dtstart", time);
			Calendar cal = Calendar.getInstance();
			cal.setTimeInMillis(time);
			cal.add(Calendar.SECOND, (int) duration);
			event.put("dtend", cal.getTimeInMillis());
			event.put("exdate", time);
			event.put("duration", duration <= 0 ? 0 : duration);
			event.put("eventStatus", 0);
			event.put("visibility", 0);
			event.put("transparency", 0);
			event.put("importance", 1);
			event.put("organizer", Thoth.Settings.USR_DEVICE_ACCOUNT_EMAIL);
			event.put("eventTimezone", TimeZone.getDefault().getID());
			event.put("_sync_account", Thoth.Settings.USR_DEVICE_ACCOUNT_EMAIL);
			event.put("_sync_account_type", "com.google");
			event.put("hasAlarm", 0);
			event.put("allDay", 0);
			try
			{
				cr.insert(Uri.withAppendedPath(CALENDAR, "events"), event).getLastPathSegment();
			}
			catch (Exception e)
			{
				ThothLog.e(e);
			}
		}
		else
			return;
	}
	
	final Handler	sHandler	= new Handler()
									{
										@Override
										public void handleMessage(Message msg)
										{
											switch (msg.what)
											{
												case 10 :
												{
													Thoth.clearNotifications();
													if (!Thoth.isNetworkOK())
													{
														Thoth.showNwkNotification();
														Thoth.Settings.APP_UPDATE_PENDING = true;
														Thoth.Settings.APP_UPDATE_IN_PROGRESS = false;
														Thoth.Settings.write();
														ThothLog.i("Could not execute update : Network was unavailable.");
														if (null != SyncMain.getInstance())
															SyncMain.getInstance().sHandler.sendEmptyMessage(1);
														if (null != TabMain.getInstance())
															TabMain.getInstance().hdlr.sendEmptyMessage(3);
														return;
													}
													Thoth.isSecureOK(new ThothAccountCallback()
													{
														@Override
														public void handle(int resultCode)
														{
															if (resultCode == 1)
																sHandler.sendEmptyMessage(0);
															else if (resultCode == -1 || resultCode == -2 || resultCode == -3)
															{
																Thoth.showSecureNotification();
																Thoth.Settings.APP_UPDATE_PENDING = true;
																Thoth.Settings.APP_UPDATE_IN_PROGRESS = false;
																ThothLog.e(new Exception("Thoth Service : Account authentication failed."));
																if (null != SyncMain.getInstance())
																	SyncMain.getInstance().sHandler.sendEmptyMessage(1);
																if (null != TabMain.getInstance())
																	TabMain.getInstance().hdlr.sendEmptyMessage(3);
															}
														}
													}, sHandler);
													break;
												}
												case 0 : // NWK is OK and Secure is OK
												{
													ThothLog.i("An update is in progress.");
													Toast.makeText(cx, "An update is in progress.", Toast.LENGTH_SHORT).show();
													connectToThothServer();
													break;
												}
												case 1 : // Analytics is complete
												{
													Thoth.Settings.APP_LAST_SYNC_THOTH = System.currentTimeMillis();
													if (null != SyncMain.getInstance())
														SyncMain.getInstance().sHandler.sendEmptyMessage(1);
													if (null != TabMain.getInstance())
														TabMain.getInstance().hdlr.sendEmptyMessage(3);
													Thoth.Settings.APP_UPDATE_PENDING = false;
													Thoth.Settings.APP_UPDATE_IN_PROGRESS = false;
													Thoth.Settings.APP_STATS_UPDATE = false;
													Thoth.Settings.write();
													ThothLog.i("Update was successful.");
													Thoth.clearNotifications();
													Toast.makeText(cx, "Update was successful.", Toast.LENGTH_SHORT).show();
													break;
												}
												case 2 : // No Update required
												{
													Thoth.Settings.APP_UPDATE_PENDING = false;
													Thoth.Settings.APP_UPDATE_IN_PROGRESS = false;
													Thoth.Settings.write();
													ThothLog.i("Update was not required.");
													Thoth.clearNotifications();
													Toast.makeText(cx, "Update was not required.", Toast.LENGTH_SHORT).show();
													break;
												}
												case 40 :
												{
													handleCallCapture();
													break;
												}
												case 1000 :
												{
													if (!Thoth.Settings.APP_UPDATE_IN_PROGRESS && !Thoth.Settings.APP_SETUP)
														sHandler.sendEmptyMessage(10);
													sHandler.sendEmptyMessageDelayed(1001, 120000);
													break;
												}
												case 1001 :
												{
													Thoth.showDailyNotification();
													break;
												}
												case -999 :
												{
													synchronized (this)
													{
														ThothAuth.authTimeout = true;
													};
													break;
												}
												case -1 : // Update failed
												{
													Thoth.Settings.APP_UPDATE_PENDING = true;
													Thoth.Settings.APP_UPDATE_IN_PROGRESS = false;
													ThothLog.e(new Exception("Thoth Service : Update failed."));
													if (null != SyncMain.getInstance())
														SyncMain.getInstance().sHandler.sendEmptyMessage(1);
													if (null != TabMain.getInstance())
														TabMain.getInstance().hdlr.sendEmptyMessage(3);
													Thoth.Settings.write();
													// Thoth.showUpdateFailNotification();
													break;
												}
											}
										}
									};
	
	@Override
	protected void onHandleIntent(final Intent intent)
	{
		cx = getApplicationContext();
		Thoth.Settings.read();
		if (intent != null)
		{
			ThothLog.d("Started Thoth-Service for action : " + intent.getAction());
			switch (Integer.parseInt(intent.getAction()))
			{
				case Thoth.REQ.CALL_CAPTURE :
				{
					if (Thoth.Settings.APP_SETUP)
						setupCallCapture();
					else
						sHandler.sendEmptyMessageDelayed(40, 3000);
					break;
				}
				case Thoth.REQ.MSGS_CAPTURE :
				{
					if (Thoth.Settings.APP_SETUP)
						setupSMSCapture();
					else
						handleSMSCapture(intent);
					break;
				}
				case Thoth.REQ.MSGM_CAPTURE :
				{
					if (Thoth.Settings.APP_SETUP)
						setupMMSCapture();
					else
						handleMMSCapture(false);
					break;
				}
				case Thoth.REQ.DATA_CAPTURE :
				{
					if (Thoth.Settings.APP_SETUP)
						setupDataCapture();
					else
						handleDataCapture();
					break;
				}
				case Thoth.REQ.UPDATE_SERVER :
				{
					if (!Thoth.Settings.APP_UPDATE_IN_PROGRESS && !Thoth.Settings.APP_SETUP)
					{
						Thoth.Settings.APP_UPDATE_IN_PROGRESS = true;
						Thoth.Settings.write();
						sHandler.sendEmptyMessage(10);
						ThothLog.d("Processed : " + intent.getAction());
					}
					break;
				}
				case 1000 :
				{
					sHandler.sendEmptyMessageDelayed(1000, 120000);
					break;
				}
				case Thoth.REQ.SYNC_CAPTURE :
				{
					missedCallCapture();
					missedSMSCapture();
					missedMMSCapture();
					break;
				}
			}
		}
	}
	
	void handleCallCapture()
	{
		new Thread(new Runnable()
		{
			@Override
			public void run()
			{
				new Runnable()
				{
					@Override
					public void run()
					{
						ContentResolver cr = getContentResolver();
						Cursor callCur = cr.query(android.provider.CallLog.Calls.CONTENT_URI, null, null, null, android.provider.CallLog.Calls.DATE + " DESC");
						callCur.moveToFirst();
						int T_C_DURATION;
						long T_C_DATETIME;
						String H_C_PKEY;
						String T_C_NUMBER, T_C_CONTACT, T_C_CONTACTNAME, T_C_TYPE;
						Log.e(Thoth.TAG, "" + Thoth.Call.count);
						ThothDB dbA = new ThothDB(cx);
						dbA.open();
						SQLiteDatabase db = dbA.getDb();
						for (int rcdCnt = 0; rcdCnt < Thoth.Call.count && rcdCnt < callCur.getCount(); rcdCnt++)
						{
							T_C_NUMBER = callCur.getString(callCur.getColumnIndex(android.provider.CallLog.Calls.NUMBER));
							T_C_CONTACT = T_C_NUMBER;
							T_C_CONTACTNAME = "UNKNOWN";
							T_C_DATETIME = callCur.getLong(callCur.getColumnIndex(android.provider.CallLog.Calls.DATE));
							T_C_DURATION = callCur.getInt(callCur.getColumnIndex(android.provider.CallLog.Calls.DURATION));
							T_C_TYPE = callCur.getString(callCur.getColumnIndex(android.provider.CallLog.Calls.TYPE));
							switch (callCur.getInt(callCur.getColumnIndex(android.provider.CallLog.Calls.TYPE)))
							{
								case android.provider.CallLog.Calls.INCOMING_TYPE :
									T_C_TYPE = (T_C_DURATION == 0) ? "2" : "0";
									break;
								case android.provider.CallLog.Calls.MISSED_TYPE :
									T_C_TYPE = "3";
									break;
								case android.provider.CallLog.Calls.OUTGOING_TYPE :
									T_C_TYPE = (T_C_DURATION == 0) ? "4" : "1";
									break;
							}
							H_C_PKEY = MD5.getMD5HEX(T_C_NUMBER + T_C_CONTACT + T_C_DATETIME + T_C_DURATION + T_C_TYPE);
							// Write to DB.
							// Insert HASH in h_Call
							ContentValues newRow = new ContentValues();
							newRow.put(ThothDB.col_H_C_PKEY, H_C_PKEY);
							try
							{
								db.insertOrThrow(ThothDB.table_HASH_CALL, "", newRow);
							}
							catch (SQLException exp)
							{
								if (callCur.moveToNext())
									continue;
								else
									break;
							}
							// Insert record into t_Call
							newRow = new ContentValues();
							newRow.put(ThothDB.col_T_C_FKEY, H_C_PKEY);
							newRow.put(ThothDB.col_T_C_NUMBER, T_C_NUMBER);
							Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(T_C_NUMBER));
							Cursor c = null;
							try
							{
								c = cr.query(uri, new String[]{PhoneLookup.LOOKUP_KEY, PhoneLookup.DISPLAY_NAME}, null, null, null);
								if (null != c && c.moveToFirst())
								{
									T_C_CONTACT = c.getString(0);
									T_C_CONTACTNAME = c.getString(1);
								}
							}
							catch (Exception e)
							{}
							finally
							{
								if (null != c)
									c.close();
							}
							newRow.put(ThothDB.col_T_C_CONTACT, T_C_CONTACT);
							newRow.put(ThothDB.col_T_C_CONTACTNAME, T_C_CONTACTNAME);
							newRow.put(ThothDB.col_T_C_DATETIME, T_C_DATETIME);
							newRow.put(ThothDB.col_T_C_DURATION, T_C_DURATION);
							newRow.put(ThothDB.col_T_C_TYPE, T_C_TYPE);
							try
							{
								db.insertOrThrow(ThothDB.table_TEMP_CALL, "", newRow);
								if (Thoth.Settings.APP_ENABLE_GoCAL)
								{
									StringBuilder title = new StringBuilder();
									StringBuilder description = new StringBuilder();
									String common = (T_C_CONTACTNAME.equalsIgnoreCase(T_C_NUMBER)) ? T_C_CONTACTNAME : T_C_CONTACTNAME + " [" + T_C_NUMBER + "]";
									switch (Integer.valueOf(T_C_TYPE))
									{
										case 0 :
											title.append("IN ").append(common);
											description.append("Incoming call from ").append(common).append("\n" + "Duration : ").append((T_C_DURATION > 59) ? Math.round(T_C_DURATION / 60) + " min." : T_C_DURATION + " sec.");
											break;
										case 1 :
											title.append("OUT ").append(common);
											description.append("Outgoing call to  ").append(common).append("\n" + "Duration : ").append((T_C_DURATION > 59) ? Math.round(T_C_DURATION / 60) + " min." : T_C_DURATION + " sec.");
											break;
										case 2 :
											title.append("REJECTED ").append(common);
											description.append("Rejected call from ").append(common);
											break;
										case 3 :
											title.append("MISSED ").append(common);
											description.append("Missed call from ").append(common);
											break;
										case 4 :
											title.append("NO-ANSWER ").append(common);
											description.append("No-answer for call to ").append(common);
											break;
									}
									updateGoogleCalendar(T_C_DATETIME, T_C_DURATION, title.toString(), description.toString());
								}
							}
							catch (SQLException e)
							{
								// ThothLog.e(e);
							}
							callCur.moveToNext();
						}
						if (db.isOpen())
							db.close();
						callCur.close();
						Thoth.Call.count = 0;
						Thoth.Call.isACTIVE = Thoth.Call.isOUTBOUND = false;
						Thoth.Settings.APP_LAST_CALL_CAPTURE = System.currentTimeMillis();
						Thoth.Settings.write();
					}
				}.run();
			}
		}).start();
	}
	
	void handleSMSCapture(final Intent intent)
	{
		new Thread(new Runnable()
		{
			@Override
			public void run()
			{
				new Runnable()
				{
					@Override
					public void run()
					{
						ContentResolver cr = getContentResolver();
						if (intent != null)
						{
							Bundle bundle = intent.getExtras();
							SmsMessage[] msgs = null;
							if (bundle != null)
							{
								Object[] pdus = (Object[]) bundle.get("pdus");
								msgs = new SmsMessage[pdus.length];
								float T_M_DATETIME;
								String H_M_PKEY;
								String T_M_NUMBER, T_M_CONTACT, T_M_CONTACTNAME, T_M_MSG, T_M_TYPE;
								ThothDB dbA = new ThothDB(cx);
								dbA.open();
								SQLiteDatabase db = dbA.getDb();
								for (int i = 0; i < msgs.length; i++)
								{
									msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
									T_M_NUMBER = msgs[i].getOriginatingAddress();
									T_M_CONTACT = T_M_NUMBER;
									T_M_CONTACTNAME = "UNKNOWN";
									T_M_DATETIME = msgs[i].getTimestampMillis();
									T_M_MSG = msgs[i].getMessageBody().toString();
									T_M_TYPE = "0";
									H_M_PKEY = MD5.getMD5HEX(T_M_NUMBER + T_M_CONTACT + T_M_DATETIME + T_M_MSG + T_M_TYPE);
									// Write to DB.
									// Insert HASH in h_Msgs
									ContentValues newRow = new ContentValues();
									newRow.put(ThothDB.col_H_M_PKEY, H_M_PKEY);
									try
									{
										db.insertOrThrow(ThothDB.table_HASH_MSGS, "", newRow);
									}
									catch (SQLException e)
									{
										// ThothLog.e(e);
										continue;
									}
									// Insert record into t_Msgs
									newRow = new ContentValues();
									newRow.put(ThothDB.col_T_M_FKEY, H_M_PKEY);
									newRow.put(ThothDB.col_T_M_NUMBER, T_M_NUMBER);
									Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(T_M_NUMBER));
									Cursor c = null;
									try
									{
										c = cr.query(uri, new String[]{PhoneLookup.LOOKUP_KEY, PhoneLookup.DISPLAY_NAME}, null, null, null);
										if (null != c && c.moveToFirst())
										{
											T_M_CONTACT = c.getString(0);
											T_M_CONTACTNAME = c.getString(1);
										}
									}
									catch (Exception e)
									{}
									finally
									{
										if (null != c)
											c.close();
									}
									newRow.put(ThothDB.col_T_M_CONTACT, T_M_CONTACT);
									newRow.put(ThothDB.col_T_M_CONTACTNAME, T_M_CONTACTNAME);
									newRow.put(ThothDB.col_T_M_DATETIME, T_M_DATETIME);
									newRow.put(ThothDB.col_T_M_MSG, T_M_MSG);
									newRow.put(ThothDB.col_T_M_TYPE, T_M_TYPE);
									try
									{
										dbA.getDb().insertOrThrow(ThothDB.table_TEMP_MSGS, "", newRow);
									}
									catch (SQLException e)
									{
										// ThothLog.e(e);
									}
								}
								if (db.isOpen())
									db.close();
							}
						}
						// SENT MESSAGES
						float T_M_DATETIME;
						String H_M_PKEY;
						String T_M_NUMBER, T_M_CONTACT, T_M_CONTACTNAME, T_M_MSG, T_M_TYPE;
						Cursor smsCur = cr.query(Uri.parse("content://sms/sent"), null, null, null, null);
						if (smsCur.getCount() > 0 && smsCur.moveToFirst())
						{
							ThothDB dbA = new ThothDB(cx);
							dbA.open();
							SQLiteDatabase db = dbA.getDb();
							for (int i = 0; i < smsCur.getCount(); i++)
							{
								T_M_NUMBER = smsCur.getString(smsCur.getColumnIndexOrThrow("address")).toString();
								T_M_CONTACT = T_M_NUMBER;
								T_M_CONTACTNAME = "UNKNOWN";
								T_M_DATETIME = smsCur.getFloat(smsCur.getColumnIndexOrThrow("date"));
								T_M_MSG = smsCur.getString(smsCur.getColumnIndexOrThrow("body")).toString();
								T_M_TYPE = "1";
								H_M_PKEY = MD5.getMD5HEX(T_M_NUMBER + (String) T_M_CONTACT + T_M_DATETIME + T_M_MSG + T_M_TYPE);
								// Write to DB.
								// Insert HASH in h_Msgs
								ContentValues newRow = new ContentValues();
								newRow.put(ThothDB.col_H_M_PKEY, H_M_PKEY);
								try
								{
									db.insertOrThrow(ThothDB.table_HASH_MSGS, "", newRow);
								}
								catch (SQLException e)
								{
									// ThothLog.e(e);
									if (smsCur.moveToNext())
										continue;
									else
										break;
								}
								// Insert record into t_Msgs
								newRow = new ContentValues();
								newRow.put(ThothDB.col_T_M_FKEY, H_M_PKEY);
								newRow.put(ThothDB.col_T_M_NUMBER, T_M_NUMBER);
								Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(T_M_NUMBER));
								Cursor c = null;
								try
								{
									c = cr.query(uri, new String[]{PhoneLookup.LOOKUP_KEY, PhoneLookup.DISPLAY_NAME}, null, null, null);
									if (null != c && c.moveToFirst())
									{
										T_M_CONTACT = c.getString(0);
										T_M_CONTACTNAME = c.getString(1);
									}
								}
								catch (Exception e)
								{}
								finally
								{
									if (null != c)
										c.close();
								}
								newRow.put(ThothDB.col_T_M_CONTACT, T_M_CONTACT);
								newRow.put(ThothDB.col_T_M_CONTACTNAME, T_M_CONTACTNAME);
								newRow.put(ThothDB.col_T_M_DATETIME, T_M_DATETIME);
								newRow.put(ThothDB.col_T_M_MSG, T_M_MSG);
								newRow.put(ThothDB.col_T_M_TYPE, T_M_TYPE);
								newRow.putNull(ThothDB.col_T_M_BLOB_TEXT);
								newRow.putNull(ThothDB.col_T_M_BLOB_DATA);
								newRow.putNull(ThothDB.col_T_M_BLOB_DATA_MIME);
								try
								{
									db.insertOrThrow(ThothDB.table_TEMP_MSGS, "", newRow);
								}
								catch (SQLException e)
								{
									// ThothLog.e(e);
								}
								smsCur.moveToNext();
							}
							if (db.isOpen())
								db.close();
						}
						smsCur.close();
						Thoth.Settings.APP_LAST_MSGS_CAPTURE = System.currentTimeMillis();
						Thoth.Settings.write();
					}
				}.run();
			}
		}).start();
	}
	
	void handleMMSCapture(final boolean isSetup)
	{
		Thread thread = new Thread()
		{
			public void run()
			{
				try
				{
					ContentResolver cr = getContentResolver();
					Cursor mmsCur = cr.query(Uri.parse("content://mms/"), null, null, null, "_id");
					if (mmsCur.getCount() > 0 && mmsCur.moveToFirst())
					{
						if (isSetup)
							SetupMain.sPbMax += mmsCur.getCount();
						ThothDB dbA = new ThothDB(cx);
						dbA.open();
						SQLiteDatabase db = dbA.getDb();
						for (int z = 0; z < mmsCur.getCount(); z++)
						{
							if (isSetup)
							{
								SetupMain.sPbCurrent++;
								Message msg = new Message();
								msg.what = 55;
								msg.arg1 = 2;
								msg.obj = new String("MMS logs (" + (z + 1) + "/" + mmsCur.getCount() + ")");
								SetupMain.getInstance().hdlr.sendMessage(msg);
							}
							float T_M_DATETIME = 0;
							String H_M_PKEY = "", T_M_NUMBER = "", T_M_CONTACT = "", T_M_CONTACTNAME = "", T_M_MSG = "", T_M_TYPE = "", T_M_BLOB_TEXT = "";
							byte[] T_M_BLOB_DATA = null;
							String T_M_BLOB_DATA_MIME = "";
							int id = Integer.parseInt(mmsCur.getString(mmsCur.getColumnIndex("_id")));
							T_M_DATETIME = 1000 * mmsCur.getLong(mmsCur.getColumnIndex("date"));
							Cursor addrCur = cr.query(Uri.parse("content://mms/" + id + "/addr"), null, "type=151", null, "_id");
							if (addrCur != null && addrCur.getCount() > 0 && addrCur.moveToFirst())
								T_M_NUMBER = addrCur.getString(addrCur.getColumnIndex("address"));
							if (T_M_NUMBER != "")
								T_M_CONTACT = T_M_NUMBER;
							else
								T_M_CONTACT = T_M_NUMBER = Thoth.Settings.USR_DEVICE_PHONE_NUMBER;
							addrCur.close();
							T_M_CONTACTNAME = "UNKNOWN";
							T_M_MSG = mmsCur.getString(mmsCur.getColumnIndex("sub"));
							T_M_TYPE = (Integer.parseInt(mmsCur.getString(mmsCur.getColumnIndex("m_type"))) == 128) ? "3" : "2";
							H_M_PKEY = MD5.getMD5HEX(id + T_M_NUMBER + T_M_CONTACT + T_M_DATETIME + T_M_MSG + T_M_TYPE);
							// Write to DB.
							// Insert HASH in h_Msgs
							ContentValues newRow = new ContentValues();
							newRow.put(ThothDB.col_H_M_PKEY, H_M_PKEY);
							try
							{
								db.insertOrThrow(ThothDB.table_HASH_MSGS, "", newRow);
							}
							catch (SQLException e)
							{
								// ThothLog.e(e);
								if (mmsCur.moveToNext())
									continue;
								else
									break;
							}
							// Get MMS message parts
							Cursor curPart = cr.query(Uri.parse("content://mms/part"), null, "mid = " + id, null, "_id");
							if (curPart.getCount() > 0 && curPart.moveToFirst())
							{
								for (int y = 0; y < curPart.getCount(); y++)
								{
									String mime = curPart.getString(curPart.getColumnIndex("ct"));
									String prtId = curPart.getString(curPart.getColumnIndex("_id"));
									if (mime.equalsIgnoreCase("text/plain"))
									{
										byte[] messageData = readMMSPart(prtId);
										if (messageData != null && messageData.length > 0)
											T_M_BLOB_TEXT = new String(messageData);
										if (T_M_BLOB_TEXT == "")
										{
											Cursor txtPartCur = cr.query(Uri.parse("content://mms/part"), null, "mid = " + id + " and _id =" + prtId, null, "_id");
											txtPartCur.moveToLast();
											T_M_BLOB_TEXT = txtPartCur.getString(txtPartCur.getColumnIndex("text"));
											if (T_M_MSG.length() == 0 && T_M_BLOB_TEXT != null)
												T_M_MSG = T_M_BLOB_TEXT;
										}
									}
									else
									{
										T_M_BLOB_DATA = readMMSPart(prtId);
										T_M_BLOB_DATA_MIME = mime;
									}
									curPart.moveToNext();
								}
							}
							newRow = new ContentValues();
							newRow.put(ThothDB.col_T_M_FKEY, H_M_PKEY);
							newRow.put(ThothDB.col_T_M_NUMBER, T_M_NUMBER);
							Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(T_M_NUMBER));
							Cursor c = null;
							try
							{
								c = cr.query(uri, new String[]{PhoneLookup.LOOKUP_KEY, PhoneLookup.DISPLAY_NAME}, null, null, null);
								if (null != c && c.moveToFirst())
								{
									T_M_CONTACT = c.getString(0);
									T_M_CONTACTNAME = c.getString(1);
								}
							}
							catch (Exception e)
							{}
							finally
							{
								if (null != c)
									c.close();
							}
							newRow.put(ThothDB.col_T_M_CONTACT, T_M_CONTACT);
							newRow.put(ThothDB.col_T_M_CONTACTNAME, T_M_CONTACTNAME);
							newRow.put(ThothDB.col_T_M_DATETIME, T_M_DATETIME);
							newRow.put(ThothDB.col_T_M_MSG, T_M_MSG);
							newRow.put(ThothDB.col_T_M_TYPE, T_M_TYPE);
							if (T_M_BLOB_TEXT != null)
								newRow.put(ThothDB.col_T_M_BLOB_TEXT, T_M_BLOB_TEXT);
							else
								newRow.putNull(ThothDB.col_T_M_BLOB_TEXT);
							if (T_M_BLOB_DATA != null)
								newRow.put(ThothDB.col_T_M_BLOB_DATA, T_M_BLOB_DATA);
							else
								newRow.putNull(ThothDB.col_T_M_BLOB_DATA);
							if (T_M_BLOB_DATA_MIME != "")
								newRow.put(ThothDB.col_T_M_BLOB_DATA_MIME, T_M_BLOB_DATA_MIME);
							else
								newRow.putNull(ThothDB.col_T_M_BLOB_DATA_MIME);
							try
							{
								db.insertOrThrow(ThothDB.table_TEMP_MSGS, "", newRow);
							}
							catch (SQLException e)
							{
								// ThothLog.e(e);
							}
							mmsCur.moveToNext();
						}
						if (db.isOpen())
							db.close();
						mmsCur.close();
						Thoth.Settings.APP_LAST_MSGM_CAPTURE = System.currentTimeMillis();
						Thoth.Settings.write();
						if (isSetup)
							SetupMain.getInstance().hdlr.sendEmptyMessage(53);
					}
					else
					{
						Thoth.Settings.APP_LAST_MSGM_CAPTURE = System.currentTimeMillis();
						Thoth.Settings.write();
						SetupMain.getInstance().hdlr.sendEmptyMessage(53);
					}
				}
				catch (Exception e)
				{
					// ThothLog.e(e);
				}
			}
		};
		thread.start();
	}
	
	void handleDataCapture()
	{
		service.submit(new Runnable()
		{
			@Override
			public void run()
			{
				long _DAYID, _BOOTID, _UPLOAD, _DOWNLOAD, _TIME;
				_DAYID = Thoth.Data.MOBILE_CURR_DAY_ID;
				_BOOTID = Thoth.Data.MOBILE_NWK_RESET;
				_UPLOAD = NetworkStatistics.getMTBytes();
				_DOWNLOAD = NetworkStatistics.getMRBytes();
				_TIME = System.currentTimeMillis();
				if (Thoth.Data.MOBILE_DAILY_CORRECTION)
				{
					Thoth.Data.MOBILE_DAILY_CORRECTION = false;
					Thoth.Data.MOBILE_DAILY_UL_CORRECTION = _UPLOAD;
					Thoth.Data.MOBILE_DAILY_DL_CORRECTION = _DOWNLOAD;
					if (Thoth.Data.MOBILE_DAILY_UL_CORRECTION >= Thoth.Data.MOBILE_DAILY_UL_CORRECTION_PREV)
					{
						_UPLOAD = Thoth.Data.MOBILE_DAILY_UL_CORRECTION - Thoth.Data.MOBILE_DAILY_UL_CORRECTION_PREV;
						Thoth.Data.MOBILE_DAILY_UL_CORRECTION_PREV += _UPLOAD;
					}
					else
						_UPLOAD = Thoth.Data.MOBILE_DAILY_UL_CORRECTION;
					if (Thoth.Data.MOBILE_DAILY_DL_CORRECTION >= Thoth.Data.MOBILE_DAILY_DL_CORRECTION_PREV)
					{
						_DOWNLOAD = Thoth.Data.MOBILE_DAILY_DL_CORRECTION - Thoth.Data.MOBILE_DAILY_DL_CORRECTION_PREV;
						Thoth.Data.MOBILE_DAILY_DL_CORRECTION_PREV += _DOWNLOAD;
					}
					else
						_DOWNLOAD = Thoth.Data.MOBILE_DAILY_DL_CORRECTION;
					Thoth.Data.write();
				}
				if (Thoth.Data.MOBILE_NEW_DAY && Thoth.Data.MOBILE_CURR_DAY_ID != Thoth.Data.MOBILE_PREV_DAY_ID)
				{
					Thoth.Data.MOBILE_NEW_DAY = false;
					Thoth.Data.MOBILE_DAILY_UL_CORRECTION_PREV = Thoth.Data.MOBILE_DAILY_UL_CORRECTION;
					Thoth.Data.MOBILE_DAILY_DL_CORRECTION_PREV = Thoth.Data.MOBILE_DAILY_DL_CORRECTION;
					_UPLOAD -= Thoth.Data.MOBILE_DAILY_UL_CORRECTION;
					_DOWNLOAD -= Thoth.Data.MOBILE_DAILY_DL_CORRECTION;
				}
				_UPLOAD = _UPLOAD < 0 ? 0 : _UPLOAD;
				_DOWNLOAD = _DOWNLOAD < 0 ? 0 : _DOWNLOAD;
				ThothDB dbA = new ThothDB(cx);
				dbA.open();
				SQLiteDatabase db = dbA.getDb();
				ContentValues newRow = new ContentValues();
				newRow.put(ThothDB.col_T_D_M_PKEY, _DAYID + _BOOTID);
				newRow.put(ThothDB.col_T_D_M_DAYID, _DAYID);
				newRow.put(ThothDB.col_T_D_M_BOOTID, _BOOTID);
				newRow.put(ThothDB.col_T_D_M_UPLOAD, _UPLOAD);
				newRow.put(ThothDB.col_T_D_M_DOWNLOAD, _DOWNLOAD);
				newRow.put(ThothDB.col_T_D_M_TIME, _TIME);
				try
				{
					db.insertOrThrow(ThothDB.table_TEMP_DATA_MOBL, "", newRow);
				}
				catch (SQLiteConstraintException e)
				{
					try
					{
						db.replaceOrThrow(ThothDB.table_TEMP_DATA_MOBL, "", newRow);
					}
					catch (Exception ee)
					{
						// ThothLog.e(ee);
					}
				}
				catch (Exception e)
				{
					// ThothLog.e(e);
				}
				if (db.isOpen())
					db.close();
			}
		});
		service.submit(new Runnable()
		{
			@Override
			public void run()
			{
				long _DAYID, _BOOTID, _UPLOAD, _DOWNLOAD, _TIME;
				_DAYID = Thoth.Data.WIFI_CURR_DAY_ID;
				_BOOTID = Thoth.Data.WIFI_NWK_RESET;
				_UPLOAD = NetworkStatistics.getTTBytes() - NetworkStatistics.getMTBytes();
				_DOWNLOAD = NetworkStatistics.getTRBytes() - NetworkStatistics.getMRBytes();
				_TIME = System.currentTimeMillis();
				if (Thoth.Data.WIFI_DAILY_CORRECTION)
				{
					Thoth.Data.WIFI_DAILY_CORRECTION = false;
					Thoth.Data.WIFI_DAILY_UL_CORRECTION = _UPLOAD;
					Thoth.Data.WIFI_DAILY_DL_CORRECTION = _DOWNLOAD;
					if (Thoth.Data.WIFI_DAILY_UL_CORRECTION >= Thoth.Data.WIFI_DAILY_UL_CORRECTION_PREV)
					{
						_UPLOAD = Thoth.Data.WIFI_DAILY_UL_CORRECTION - Thoth.Data.WIFI_DAILY_UL_CORRECTION_PREV;
						Thoth.Data.WIFI_DAILY_UL_CORRECTION_PREV += _UPLOAD;
					}
					else
						_UPLOAD = Thoth.Data.WIFI_DAILY_UL_CORRECTION;
					if (Thoth.Data.WIFI_DAILY_DL_CORRECTION >= Thoth.Data.WIFI_DAILY_DL_CORRECTION_PREV)
					{
						_DOWNLOAD = Thoth.Data.WIFI_DAILY_DL_CORRECTION - Thoth.Data.WIFI_DAILY_DL_CORRECTION_PREV;
						Thoth.Data.WIFI_DAILY_DL_CORRECTION_PREV += _DOWNLOAD;
					}
					else
						_DOWNLOAD = Thoth.Data.WIFI_DAILY_DL_CORRECTION;
					Thoth.Data.WIFI_INTRADAY_UL_CORRECTION = Thoth.Data.WIFI_INTRADAY_UL_CORRECTION_PREV = 0;
					Thoth.Data.WIFI_INTRADAY_DL_CORRECTION = Thoth.Data.WIFI_INTRADAY_DL_CORRECTION_PREV = 0;
					Thoth.Data.write();
				}
				if (Thoth.Data.WIFI_INTRADAY_CORRECTION)
				{
					Thoth.Data.WIFI_INTRADAY_CORRECTION = false;
					Thoth.Data.WIFI_INTRADAY_UL_CORRECTION = _UPLOAD - Thoth.Data.WIFI_DAILY_UL_CORRECTION;
					Thoth.Data.WIFI_INTRADAY_DL_CORRECTION = _DOWNLOAD - Thoth.Data.WIFI_DAILY_DL_CORRECTION;
					if (Thoth.Data.WIFI_INTRADAY_UL_CORRECTION > Thoth.Data.WIFI_INTRADAY_UL_CORRECTION_PREV)
					{
						_UPLOAD = Thoth.Data.WIFI_INTRADAY_UL_CORRECTION - Thoth.Data.WIFI_INTRADAY_UL_CORRECTION_PREV;
						Thoth.Data.WIFI_INTRADAY_UL_CORRECTION_PREV += _UPLOAD;
					}
					else
						_UPLOAD = 0;
					if (Thoth.Data.WIFI_INTRADAY_DL_CORRECTION > Thoth.Data.WIFI_INTRADAY_DL_CORRECTION_PREV)
					{
						_DOWNLOAD = Thoth.Data.WIFI_INTRADAY_DL_CORRECTION - Thoth.Data.WIFI_INTRADAY_DL_CORRECTION_PREV;
						Thoth.Data.WIFI_INTRADAY_DL_CORRECTION_PREV += _DOWNLOAD;
					}
					else
						_DOWNLOAD = 0;
					Thoth.Data.write();
				}
				if (Thoth.Data.WIFI_NEW_DAY && Thoth.Data.WIFI_CURR_DAY_ID != Thoth.Data.WIFI_PREV_DAY_ID)
				{
					Thoth.Data.WIFI_NEW_DAY = false;
					Thoth.Data.WIFI_DAILY_UL_CORRECTION_PREV = Thoth.Data.WIFI_DAILY_UL_CORRECTION;
					Thoth.Data.WIFI_DAILY_DL_CORRECTION_PREV = Thoth.Data.WIFI_DAILY_DL_CORRECTION;
					_UPLOAD -= Thoth.Data.WIFI_DAILY_UL_CORRECTION;
					_DOWNLOAD -= Thoth.Data.WIFI_DAILY_DL_CORRECTION;
				}
				_UPLOAD = _UPLOAD < 0 ? 0 : _UPLOAD;
				_DOWNLOAD = _DOWNLOAD < 0 ? 0 : _DOWNLOAD;
				if (_UPLOAD < 1 || _DOWNLOAD < 1)
					_BOOTID = Thoth.Data.WIFI_NWK_RESET = System.currentTimeMillis();
				ThothDB dbA = new ThothDB(cx);
				dbA.open();
				SQLiteDatabase db = dbA.getDb();
				ContentValues newRow = new ContentValues();
				newRow.put(ThothDB.col_T_D_W_PKEY, _DAYID + _BOOTID);
				newRow.put(ThothDB.col_T_D_W_DAYID, _DAYID);
				newRow.put(ThothDB.col_T_D_W_BOOTID, _BOOTID);
				newRow.put(ThothDB.col_T_D_W_UPLOAD, _UPLOAD);
				newRow.put(ThothDB.col_T_D_W_DOWNLOAD, _DOWNLOAD);
				newRow.put(ThothDB.col_T_D_W_TIME, _TIME);
				try
				{
					db.insertOrThrow(ThothDB.table_TEMP_DATA_WIFI, "", newRow);
				}
				catch (SQLiteConstraintException e)
				{
					try
					{
						db.replaceOrThrow(ThothDB.table_TEMP_DATA_WIFI, "", newRow);
					}
					catch (Exception ee)
					{
						// ThothLog.e(ee);
					}
				}
				catch (Exception e)
				{
					// ThothLog.e(e);
				}
				if (db.isOpen())
					db.close();
			}
		});
		service.submit(new Runnable()
		{
			@Override
			public void run()
			{
				final PackageManager pkgMgr = getPackageManager();
				ThothDB dbA = new ThothDB(cx);
				dbA.open();
				SQLiteDatabase db = dbA.getDb();
				List<PackageInfo> appList = pkgMgr.getInstalledPackages(0);
				for (PackageInfo app : appList)
				{
					if (!((app.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0))
					{
						int appUID = app.applicationInfo.uid;
						String appName = app.applicationInfo.loadLabel(getPackageManager()).toString();
						String appPackage = app.packageName;
						String appUIDName = pkgMgr.getNameForUid(appUID);
						long appUpload = NetworkStatistics.getATBytes(appUID);
						long appDownload = NetworkStatistics.getARBytes(appUID);
						long appDayId = Thoth.Data.CURR_DAY_ID;
						long appBootId = Thoth.Data.DATA_RESET;
						ContentValues newRow = new ContentValues();
						newRow.put(ThothDB.col_H_A_PKEY, appPackage);
						try
						{
							db.insertOrThrow(ThothDB.table_HASH_APPS, "", newRow);
						}
						catch (SQLiteConstraintException e)
						{}
						catch (Exception e)
						{
							e.printStackTrace();
						}
						long UL_CORRECTION = appUpload, UL_CORRECTION_PREV = 0, DL_CORRECTION = appDownload, DL_CORRECTION_PREV = 0;
						Cursor cR = db.rawQuery("SELECT SUM(" + ThothDB.col_T_A_UPLOAD + "), SUM(" + ThothDB.col_T_A_DOWNLOAD + ") FROM " + ThothDB.table_TEMP_APPS + " WHERE " + ThothDB.col_T_A_PKG + "='" + appPackage + "' AND " + ThothDB.col_T_A_DAYID + "=" + Thoth.Data.PREV_DAY_ID + " AND " + ThothDB.col_T_A_BOOTID + "=" + appBootId + " GROUP BY " + ThothDB.col_T_A_DAYID, null);
						if (null != cR && cR.moveToFirst())
						{
							UL_CORRECTION_PREV = cR.getLong(0);
							DL_CORRECTION_PREV = cR.getLong(1);
							cR.close();
						}
						appUpload = (UL_CORRECTION >= UL_CORRECTION_PREV) ? (UL_CORRECTION - UL_CORRECTION_PREV) : UL_CORRECTION;
						appDownload = (DL_CORRECTION >= DL_CORRECTION_PREV) ? (DL_CORRECTION - DL_CORRECTION_PREV) : DL_CORRECTION;
						if (appUpload < 1 && appDownload < 1)
							continue;
						newRow = new ContentValues();
						newRow.put(ThothDB.col_T_A_PKG, appPackage);
						newRow.put(ThothDB.col_T_A_NAME, appName);
						newRow.put(ThothDB.col_T_A_UID, appUID);
						newRow.put(ThothDB.col_T_A_UID_NAME, appUIDName);
						newRow.put(ThothDB.col_T_A_DAYID, appDayId);
						newRow.put(ThothDB.col_T_A_BOOTID, appBootId);
						newRow.put(ThothDB.col_T_A_UPLOAD, appUpload);
						newRow.put(ThothDB.col_T_A_DOWNLOAD, appDownload);
						try
						{
							db.insertOrThrow(ThothDB.table_TEMP_APPS, "", newRow);
						}
						catch (Exception e)
						{
							// ThothLog.e(e);
						}
					}
				}
				if (db.isOpen())
					db.close();
				Thoth.Settings.APP_LAST_DATA_CAPTURE = System.currentTimeMillis();
				Thoth.Settings.write();
			}
		});
	}
	
	void setupCallCapture()
	{
		service.submit(new Runnable()
		{
			@Override
			public void run()
			{
				ContentResolver cr = getContentResolver();
				Cursor callCur = cr.query(android.provider.CallLog.Calls.CONTENT_URI, null, null, null, android.provider.CallLog.Calls.DATE + " DESC");
				if (callCur == null || !callCur.moveToFirst())
				{
					Message msg = new Message();
					msg.what = 666;
					msg.arg1 = Thoth.REQ.CALL_CAPTURE;
					sHandler.sendMessage(msg);
					return;
				}
				int T_C_DURATION;
				long T_C_DATETIME;
				String H_C_PKEY;
				String T_C_NUMBER, T_C_CONTACT, T_C_CONTACTNAME, T_C_TYPE;
				SetupMain.sPbMax += callCur.getCount();
				ThothDB dbA = new ThothDB(cx);
				dbA.open();
				SQLiteDatabase db = dbA.getDb();
				for (int k = 0; k < callCur.getCount(); k++)
				{
					SetupMain.sPbCurrent++;
					Message msg = new Message();
					msg.what = 55;
					msg.arg1 = 0;
					msg.obj = new String("CALL logs (" + (k + 1) + "/" + callCur.getCount() + ")");
					SetupMain.getInstance().hdlr.sendMessage(msg);
					T_C_NUMBER = callCur.getString(callCur.getColumnIndex(android.provider.CallLog.Calls.NUMBER));
					T_C_CONTACT = T_C_NUMBER;
					T_C_CONTACTNAME = "UNKNOWN";
					T_C_DATETIME = callCur.getLong(callCur.getColumnIndex(android.provider.CallLog.Calls.DATE));
					T_C_DURATION = callCur.getInt(callCur.getColumnIndex(android.provider.CallLog.Calls.DURATION));
					T_C_TYPE = callCur.getString(callCur.getColumnIndex(android.provider.CallLog.Calls.TYPE));
					switch (callCur.getInt(callCur.getColumnIndex(android.provider.CallLog.Calls.TYPE)))
					{
						case android.provider.CallLog.Calls.INCOMING_TYPE :
							T_C_TYPE = (T_C_DURATION == 0) ? "2" : "0";
							break;
						case android.provider.CallLog.Calls.MISSED_TYPE :
							T_C_TYPE = "3";
							break;
						case android.provider.CallLog.Calls.OUTGOING_TYPE :
							T_C_TYPE = (T_C_DURATION == 0) ? "4" : "1";
							break;
					}
					H_C_PKEY = T_C_NUMBER + T_C_CONTACT + T_C_DATETIME + T_C_DURATION + T_C_TYPE;
					// Write to DB.
					// Insert HASH in h_Call
					ContentValues newRow = new ContentValues();
					newRow.put(ThothDB.col_H_C_PKEY, H_C_PKEY);
					try
					{
						db.insertOrThrow(ThothDB.table_HASH_CALL, "", newRow);
					}
					catch (SQLException exp)
					{
						// ThothLog.e(e);
						if (callCur.moveToNext())
							continue;
						else
							break;
					}
					// Insert record into t_Call
					newRow = new ContentValues();
					newRow.put(ThothDB.col_T_C_FKEY, H_C_PKEY);
					newRow.put(ThothDB.col_T_C_NUMBER, T_C_NUMBER);
					Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(T_C_NUMBER));
					Cursor c = null;
					try
					{
						c = cr.query(uri, new String[]{PhoneLookup.LOOKUP_KEY, PhoneLookup.DISPLAY_NAME}, null, null, null);
						if (null != c && c.moveToFirst())
						{
							T_C_CONTACT = c.getString(0);
							T_C_CONTACTNAME = c.getString(1);
						}
					}
					catch (Exception e)
					{}
					finally
					{
						if (null != c)
							c.close();
					}
					newRow.put(ThothDB.col_T_C_CONTACT, T_C_CONTACT);
					newRow.put(ThothDB.col_T_C_CONTACTNAME, T_C_CONTACTNAME);
					newRow.put(ThothDB.col_T_C_DATETIME, T_C_DATETIME);
					newRow.put(ThothDB.col_T_C_DURATION, T_C_DURATION);
					newRow.put(ThothDB.col_T_C_TYPE, T_C_TYPE);
					try
					{
						db.insertOrThrow(ThothDB.table_TEMP_CALL, "", newRow);
					}
					catch (SQLException e)
					{
						// ThothLog.e(e);
					}
					callCur.moveToNext();
				}
				if (db.isOpen())
					db.close();
				callCur.close();
				Thoth.Settings.APP_LAST_CALL_CAPTURE = System.currentTimeMillis();
				Thoth.Settings.write();
				SetupMain.getInstance().hdlr.sendEmptyMessage(51);
			}
		});
	}
	
	void setupSMSCapture()
	{
		service.submit(new Runnable()
		{
			@Override
			public void run()
			{
				float T_M_DATETIME;
				String H_M_PKEY;
				String T_M_NUMBER, T_M_CONTACT, T_M_CONTACTNAME, T_M_MSG, T_M_TYPE;
				ContentResolver cr = getContentResolver();
				Cursor smsCur = cr.query(Uri.parse("content://sms"), null, null, null, null);
				if (!smsCur.moveToFirst())
				{
					Message msg = new Message();
					msg.what = 666;
					msg.arg1 = Thoth.REQ.MSGS_CAPTURE;
					sHandler.sendMessage(msg);
					return;
				}
				SetupMain.sPbMax += smsCur.getCount();
				ThothDB dbA = new ThothDB(cx);
				dbA.open();
				SQLiteDatabase db = dbA.getDb();
				for (int i = 0; i < smsCur.getCount(); i++)
				{
					SetupMain.sPbCurrent++;
					Message msg = new Message();
					msg.what = 55;
					msg.arg1 = 1;
					msg.obj = new String("SMS logs (" + (i + 1) + "/" + smsCur.getCount() + ")");
					SetupMain.getInstance().hdlr.sendMessage(msg);
					T_M_NUMBER = smsCur.getString(smsCur.getColumnIndexOrThrow("address")).toString();
					T_M_CONTACT = T_M_NUMBER;
					T_M_CONTACTNAME = "UNKNOWN";
					T_M_DATETIME = smsCur.getFloat(smsCur.getColumnIndexOrThrow("date"));
					T_M_MSG = smsCur.getString(smsCur.getColumnIndexOrThrow("body")).toString();
					T_M_TYPE = smsCur.getString(smsCur.getColumnIndexOrThrow("type")).toString();
					if (Integer.parseInt(T_M_TYPE) == 1 || Integer.parseInt(T_M_TYPE) == 2)
					{
						T_M_TYPE = (Integer.parseInt(T_M_TYPE) == 1) ? "0" : "1";
						H_M_PKEY = MD5.getMD5HEX(T_M_NUMBER + T_M_CONTACT + T_M_DATETIME + T_M_MSG + T_M_TYPE);
						// Write to DB.
						// Insert HASH in h_Msgs
						ContentValues newRow = new ContentValues();
						newRow.put(ThothDB.col_H_M_PKEY, H_M_PKEY);
						try
						{
							db.insertOrThrow(ThothDB.table_HASH_MSGS, "", newRow);
						}
						catch (SQLException exp)
						{
							// ThothLog.e(e);
							if (smsCur.moveToNext())
								continue;
							else
								break;
						}
						// Insert record into t_Msgs
						newRow = new ContentValues();
						newRow.put(ThothDB.col_T_M_FKEY, H_M_PKEY);
						newRow.put(ThothDB.col_T_M_NUMBER, T_M_NUMBER);
						Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(T_M_NUMBER));
						Cursor c = null;
						try
						{
							c = cr.query(uri, new String[]{PhoneLookup.LOOKUP_KEY, PhoneLookup.DISPLAY_NAME}, null, null, null);
							if (null != c && c.moveToFirst())
							{
								T_M_CONTACT = c.getString(0);
								T_M_CONTACTNAME = c.getString(1);
							}
						}
						catch (Exception e)
						{}
						finally
						{
							if (null != c)
								c.close();
						}
						newRow.put(ThothDB.col_T_M_CONTACT, T_M_CONTACT);
						newRow.put(ThothDB.col_T_M_CONTACTNAME, T_M_CONTACTNAME);
						newRow.put(ThothDB.col_T_M_DATETIME, T_M_DATETIME);
						newRow.put(ThothDB.col_T_M_MSG, T_M_MSG);
						newRow.put(ThothDB.col_T_M_TYPE, T_M_TYPE);
						newRow.putNull(ThothDB.col_T_M_BLOB_TEXT);
						newRow.putNull(ThothDB.col_T_M_BLOB_DATA);
						newRow.putNull(ThothDB.col_T_M_BLOB_DATA_MIME);
						try
						{
							db.insertOrThrow(ThothDB.table_TEMP_MSGS, "", newRow);
						}
						catch (SQLException e)
						{
							// ThothLog.e(e);
						}
						catch (Exception e)
						{
							// ThothLog.e(e);
						}
						smsCur.moveToNext();
					}
					else
					{
						smsCur.moveToNext();
						continue;
					}
				}
				if (db.isOpen())
					db.close();
				smsCur.close();
				Thoth.Settings.APP_LAST_MSGS_CAPTURE = System.currentTimeMillis();
				Thoth.Settings.write();
				SetupMain.getInstance().hdlr.sendEmptyMessage(52);
			}
		});
	}
	
	void setupMMSCapture()
	{
		service.submit(new Runnable()
		{
			@Override
			public void run()
			{
				handleMMSCapture(true);
			};
		});
	}
	
	void setupDataCapture()
	{
		service.submit(new Runnable()
		{
			@Override
			public void run()
			{
				long _DAYID, _BOOTID, _UPLOAD, _DOWNLOAD, _TIME;
				_DAYID = Thoth.Data.MOBILE_CURR_DAY_ID;
				_BOOTID = Thoth.Data.MOBILE_NWK_RESET;
				_UPLOAD = NetworkStatistics.getMTBytes();
				_DOWNLOAD = NetworkStatistics.getMRBytes();
				_TIME = System.currentTimeMillis();
				if (Thoth.Data.MOBILE_DAILY_CORRECTION)
				{
					Thoth.Data.MOBILE_DAILY_CORRECTION = false;
					Thoth.Data.MOBILE_DAILY_UL_CORRECTION = _UPLOAD;
					Thoth.Data.MOBILE_DAILY_DL_CORRECTION = _DOWNLOAD;
					if (Thoth.Data.MOBILE_DAILY_UL_CORRECTION >= Thoth.Data.MOBILE_DAILY_UL_CORRECTION_PREV)
					{
						_UPLOAD = Thoth.Data.MOBILE_DAILY_UL_CORRECTION - Thoth.Data.MOBILE_DAILY_UL_CORRECTION_PREV;
						Thoth.Data.MOBILE_DAILY_UL_CORRECTION_PREV += _UPLOAD;
					}
					else
						_UPLOAD = Thoth.Data.MOBILE_DAILY_UL_CORRECTION;
					if (Thoth.Data.MOBILE_DAILY_DL_CORRECTION >= Thoth.Data.MOBILE_DAILY_DL_CORRECTION_PREV)
					{
						_DOWNLOAD = Thoth.Data.MOBILE_DAILY_DL_CORRECTION - Thoth.Data.MOBILE_DAILY_DL_CORRECTION_PREV;
						Thoth.Data.MOBILE_DAILY_DL_CORRECTION_PREV += _DOWNLOAD;
					}
					else
						_DOWNLOAD = Thoth.Data.MOBILE_DAILY_DL_CORRECTION;
					Thoth.Data.write();
				}
				if (Thoth.Data.MOBILE_NEW_DAY && Thoth.Data.MOBILE_CURR_DAY_ID != Thoth.Data.MOBILE_PREV_DAY_ID)
				{
					Thoth.Data.MOBILE_NEW_DAY = false;
					Thoth.Data.MOBILE_DAILY_UL_CORRECTION_PREV = Thoth.Data.MOBILE_DAILY_UL_CORRECTION;
					Thoth.Data.MOBILE_DAILY_DL_CORRECTION_PREV = Thoth.Data.MOBILE_DAILY_DL_CORRECTION;
					_UPLOAD -= Thoth.Data.MOBILE_DAILY_UL_CORRECTION;
					_DOWNLOAD -= Thoth.Data.MOBILE_DAILY_DL_CORRECTION;
				}
				_UPLOAD = _UPLOAD < 0 ? 0 : _UPLOAD;
				_DOWNLOAD = _DOWNLOAD < 0 ? 0 : _DOWNLOAD;
				ThothDB dbA = new ThothDB(cx);
				dbA.open();
				SQLiteDatabase db = dbA.getDb();
				ContentValues newRow = new ContentValues();
				newRow.put(ThothDB.col_T_D_M_PKEY, _DAYID + _BOOTID);
				newRow.put(ThothDB.col_T_D_M_DAYID, _DAYID);
				newRow.put(ThothDB.col_T_D_M_BOOTID, _BOOTID);
				newRow.put(ThothDB.col_T_D_M_UPLOAD, _UPLOAD);
				newRow.put(ThothDB.col_T_D_M_DOWNLOAD, _DOWNLOAD);
				newRow.put(ThothDB.col_T_D_M_TIME, _TIME);
				try
				{
					db.insertOrThrow(ThothDB.table_TEMP_DATA_MOBL, "", newRow);
				}
				catch (SQLiteConstraintException e)
				{
					try
					{
						db.replaceOrThrow(ThothDB.table_TEMP_DATA_MOBL, "", newRow);
					}
					catch (Exception ee)
					{
						// ThothLog.e(ee);
					}
				}
				catch (Exception e)
				{
					// ThothLog.e(e);
				}
				if (db.isOpen())
					db.close();
			}
		});
		service.submit(new Runnable()
		{
			@Override
			public void run()
			{
				long _DAYID, _BOOTID, _UPLOAD, _DOWNLOAD, _TIME;
				_DAYID = Thoth.Data.WIFI_CURR_DAY_ID;
				_BOOTID = Thoth.Data.WIFI_NWK_RESET;
				_UPLOAD = NetworkStatistics.getTTBytes() - NetworkStatistics.getMTBytes();
				_DOWNLOAD = NetworkStatistics.getTRBytes() - NetworkStatistics.getMRBytes();
				_TIME = System.currentTimeMillis();
				if (Thoth.Data.WIFI_DAILY_CORRECTION)
				{
					Thoth.Data.WIFI_DAILY_CORRECTION = false;
					Thoth.Data.WIFI_DAILY_UL_CORRECTION = _UPLOAD;
					Thoth.Data.WIFI_DAILY_DL_CORRECTION = _DOWNLOAD;
					if (Thoth.Data.WIFI_DAILY_UL_CORRECTION >= Thoth.Data.WIFI_DAILY_UL_CORRECTION_PREV)
					{
						_UPLOAD = Thoth.Data.WIFI_DAILY_UL_CORRECTION - Thoth.Data.WIFI_DAILY_UL_CORRECTION_PREV;
						Thoth.Data.WIFI_DAILY_UL_CORRECTION_PREV += _UPLOAD;
					}
					else
						_UPLOAD = Thoth.Data.WIFI_DAILY_UL_CORRECTION;
					if (Thoth.Data.WIFI_DAILY_DL_CORRECTION >= Thoth.Data.WIFI_DAILY_DL_CORRECTION_PREV)
					{
						_DOWNLOAD = Thoth.Data.WIFI_DAILY_DL_CORRECTION - Thoth.Data.WIFI_DAILY_DL_CORRECTION_PREV;
						Thoth.Data.WIFI_DAILY_DL_CORRECTION_PREV += _DOWNLOAD;
					}
					else
						_DOWNLOAD = Thoth.Data.WIFI_DAILY_DL_CORRECTION;
					Thoth.Data.WIFI_INTRADAY_UL_CORRECTION = Thoth.Data.WIFI_INTRADAY_UL_CORRECTION_PREV = 0;
					Thoth.Data.WIFI_INTRADAY_DL_CORRECTION = Thoth.Data.WIFI_INTRADAY_DL_CORRECTION_PREV = 0;
					Thoth.Data.write();
				}
				if (Thoth.Data.WIFI_INTRADAY_CORRECTION)
				{
					Thoth.Data.WIFI_INTRADAY_CORRECTION = false;
					Thoth.Data.WIFI_INTRADAY_UL_CORRECTION = _UPLOAD - Thoth.Data.WIFI_DAILY_UL_CORRECTION;
					Thoth.Data.WIFI_INTRADAY_DL_CORRECTION = _DOWNLOAD - Thoth.Data.WIFI_DAILY_DL_CORRECTION;
					if (Thoth.Data.WIFI_INTRADAY_UL_CORRECTION > Thoth.Data.WIFI_INTRADAY_UL_CORRECTION_PREV)
					{
						_UPLOAD = Thoth.Data.WIFI_INTRADAY_UL_CORRECTION - Thoth.Data.WIFI_INTRADAY_UL_CORRECTION_PREV;
						Thoth.Data.WIFI_INTRADAY_UL_CORRECTION_PREV += _UPLOAD;
					}
					else
						_UPLOAD = 0;
					if (Thoth.Data.WIFI_INTRADAY_DL_CORRECTION > Thoth.Data.WIFI_INTRADAY_DL_CORRECTION_PREV)
					{
						_DOWNLOAD = Thoth.Data.WIFI_INTRADAY_DL_CORRECTION - Thoth.Data.WIFI_INTRADAY_DL_CORRECTION_PREV;
						Thoth.Data.WIFI_INTRADAY_DL_CORRECTION_PREV += _DOWNLOAD;
					}
					else
						_DOWNLOAD = 0;
					Thoth.Data.write();
				}
				if (Thoth.Data.WIFI_NEW_DAY && Thoth.Data.WIFI_CURR_DAY_ID != Thoth.Data.WIFI_PREV_DAY_ID)
				{
					Thoth.Data.WIFI_NEW_DAY = false;
					Thoth.Data.WIFI_DAILY_UL_CORRECTION_PREV = Thoth.Data.WIFI_DAILY_UL_CORRECTION;
					Thoth.Data.WIFI_DAILY_DL_CORRECTION_PREV = Thoth.Data.WIFI_DAILY_DL_CORRECTION;
					_UPLOAD -= Thoth.Data.WIFI_DAILY_UL_CORRECTION;
					_DOWNLOAD -= Thoth.Data.WIFI_DAILY_DL_CORRECTION;
				}
				_UPLOAD = _UPLOAD < 0 ? 0 : _UPLOAD;
				_DOWNLOAD = _DOWNLOAD < 0 ? 0 : _DOWNLOAD;
				if (_UPLOAD < 1 || _DOWNLOAD < 1)
					_BOOTID = Thoth.Data.WIFI_NWK_RESET = System.currentTimeMillis();
				ThothDB dbA = new ThothDB(cx);
				dbA.open();
				SQLiteDatabase db = dbA.getDb();
				ContentValues newRow = new ContentValues();
				newRow.put(ThothDB.col_T_D_W_PKEY, _DAYID + _BOOTID);
				newRow.put(ThothDB.col_T_D_W_DAYID, _DAYID);
				newRow.put(ThothDB.col_T_D_W_BOOTID, _BOOTID);
				newRow.put(ThothDB.col_T_D_W_UPLOAD, _UPLOAD);
				newRow.put(ThothDB.col_T_D_W_DOWNLOAD, _DOWNLOAD);
				newRow.put(ThothDB.col_T_D_W_TIME, _TIME);
				try
				{
					db.insertOrThrow(ThothDB.table_TEMP_DATA_WIFI, "", newRow);
				}
				catch (SQLiteConstraintException e)
				{
					try
					{
						db.replaceOrThrow(ThothDB.table_TEMP_DATA_WIFI, "", newRow);
					}
					catch (Exception ee)
					{
						// ThothLog.e(ee);
					}
				}
				catch (Exception e)
				{
					// ThothLog.e(e);
				}
				if (db.isOpen())
					db.close();
			}
		});
		service.submit(new Runnable()
		{
			@Override
			public void run()
			{
				final PackageManager pkgMgr = getPackageManager();
				ThothDB dbA = new ThothDB(cx);
				dbA.open();
				SQLiteDatabase db = dbA.getDb();
				List<PackageInfo> appList = pkgMgr.getInstalledPackages(0);
				SetupMain.sPbMax += appList.size();
				int i = 0;
				for (PackageInfo app : appList)
				{
					SetupMain.sPbCurrent++;
					Message msg = new Message();
					msg.what = 55;
					msg.arg1 = 3;
					msg.obj = new String("Data logs (" + (++i) + "/" + appList.size() + ")");
					SetupMain.getInstance().hdlr.sendMessage(msg);
					if (!((app.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0))
					{
						int appUID = app.applicationInfo.uid;
						String appName = app.applicationInfo.loadLabel(getPackageManager()).toString();
						String appPackage = app.packageName;
						String appUIDName = pkgMgr.getNameForUid(appUID);
						long appUpload = NetworkStatistics.getATBytes(appUID);
						long appDownload = NetworkStatistics.getARBytes(appUID);
						long appDayId = Thoth.Data.CURR_DAY_ID;
						long appBootId = Thoth.Data.DATA_RESET;
						ContentValues newRow = new ContentValues();
						newRow.put(ThothDB.col_H_A_PKEY, appPackage);
						try
						{
							db.insertOrThrow(ThothDB.table_HASH_APPS, "", newRow);
						}
						catch (SQLiteConstraintException e)
						{}
						catch (Exception e)
						{
							e.printStackTrace();
						}
						long UL_CORRECTION = appUpload, UL_CORRECTION_PREV = 0, DL_CORRECTION = appDownload, DL_CORRECTION_PREV = 0;
						Cursor cR = db.rawQuery("SELECT SUM(" + ThothDB.col_T_A_UPLOAD + "), SUM(" + ThothDB.col_T_A_DOWNLOAD + ") FROM " + ThothDB.table_TEMP_APPS + " WHERE " + ThothDB.col_T_A_PKG + "='" + appPackage + "' AND " + ThothDB.col_T_A_DAYID + "=" + Thoth.Data.PREV_DAY_ID + " AND " + ThothDB.col_T_A_BOOTID + "=" + appBootId + " GROUP BY " + ThothDB.col_T_A_DAYID, null);
						if (null != cR && cR.moveToFirst())
						{
							UL_CORRECTION_PREV = cR.getLong(0);
							DL_CORRECTION_PREV = cR.getLong(1);
							cR.close();
						}
						appUpload = (UL_CORRECTION >= UL_CORRECTION_PREV) ? (UL_CORRECTION - UL_CORRECTION_PREV) : UL_CORRECTION;
						appDownload = (DL_CORRECTION >= DL_CORRECTION_PREV) ? (DL_CORRECTION - DL_CORRECTION_PREV) : DL_CORRECTION;
						if (appUpload < 1 && appDownload < 1)
							continue;
						newRow = new ContentValues();
						newRow.put(ThothDB.col_T_A_PKG, appPackage);
						newRow.put(ThothDB.col_T_A_NAME, appName);
						newRow.put(ThothDB.col_T_A_UID, appUID);
						newRow.put(ThothDB.col_T_A_UID_NAME, appUIDName);
						newRow.put(ThothDB.col_T_A_DAYID, appDayId);
						newRow.put(ThothDB.col_T_A_BOOTID, appBootId);
						newRow.put(ThothDB.col_T_A_UPLOAD, appUpload);
						newRow.put(ThothDB.col_T_A_DOWNLOAD, appDownload);
						try
						{
							db.insertOrThrow(ThothDB.table_TEMP_APPS, "", newRow);
						}
						catch (Exception e)
						{
							// ThothLog.e(e);
						}
					}
				}
				if (db.isOpen())
					db.close();
				Thoth.Settings.APP_LAST_DATA_CAPTURE = System.currentTimeMillis();
				Thoth.Settings.write();
				SetupMain.getInstance().hdlr.sendEmptyMessage(54);
			}
		});
	}
	
	void missedCallCapture()
	{
		service.submit(new Runnable()
		{
			@Override
			public void run()
			{
				ContentResolver cr = getContentResolver();
				Cursor callCur = cr.query(android.provider.CallLog.Calls.CONTENT_URI, null, null, null, android.provider.CallLog.Calls.DATE + " DESC");
				if (callCur == null || !callCur.moveToFirst())
					return;
				int T_C_DURATION;
				long T_C_DATETIME;
				String H_C_PKEY;
				String T_C_NUMBER, T_C_CONTACT, T_C_CONTACTNAME, T_C_TYPE;
				ThothDB dbA = new ThothDB(cx);
				dbA.open();
				SQLiteDatabase db = dbA.getDb();
				for (int k = 0; k < 100 && k < callCur.getCount(); k++)
				{
					T_C_NUMBER = callCur.getString(callCur.getColumnIndex(android.provider.CallLog.Calls.NUMBER));
					T_C_CONTACT = T_C_NUMBER;
					T_C_CONTACTNAME = "UNKNOWN";
					T_C_DATETIME = callCur.getLong(callCur.getColumnIndex(android.provider.CallLog.Calls.DATE));
					T_C_DURATION = callCur.getInt(callCur.getColumnIndex(android.provider.CallLog.Calls.DURATION));
					T_C_TYPE = callCur.getString(callCur.getColumnIndex(android.provider.CallLog.Calls.TYPE));
					switch (callCur.getInt(callCur.getColumnIndex(android.provider.CallLog.Calls.TYPE)))
					{
						case android.provider.CallLog.Calls.INCOMING_TYPE :
							T_C_TYPE = (T_C_DURATION == 0) ? "2" : "0";
							break;
						case android.provider.CallLog.Calls.MISSED_TYPE :
							T_C_TYPE = "3";
							break;
						case android.provider.CallLog.Calls.OUTGOING_TYPE :
							T_C_TYPE = (T_C_DURATION == 0) ? "4" : "1";
							break;
					}
					H_C_PKEY = T_C_NUMBER + T_C_CONTACT + T_C_DATETIME + T_C_DURATION + T_C_TYPE;
					// Write to DB.
					// Insert HASH in h_Call
					ContentValues newRow = new ContentValues();
					newRow.put(ThothDB.col_H_C_PKEY, H_C_PKEY);
					try
					{
						db.insertOrThrow(ThothDB.table_HASH_CALL, "", newRow);
					}
					catch (SQLException exp)
					{
						// ThothLog.e(e);
						if (callCur.moveToNext())
							continue;
						else
							break;
					}
					// Insert record into t_Call
					newRow = new ContentValues();
					newRow.put(ThothDB.col_T_C_FKEY, H_C_PKEY);
					newRow.put(ThothDB.col_T_C_NUMBER, T_C_NUMBER);
					Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(T_C_NUMBER));
					Cursor c = null;
					try
					{
						c = cr.query(uri, new String[]{PhoneLookup.LOOKUP_KEY, PhoneLookup.DISPLAY_NAME}, null, null, null);
						if (null != c && c.moveToFirst())
						{
							T_C_CONTACT = c.getString(0);
							T_C_CONTACTNAME = c.getString(1);
						}
					}
					catch (Exception e)
					{}
					finally
					{
						if (null != c)
							c.close();
					}
					newRow.put(ThothDB.col_T_C_CONTACT, T_C_CONTACT);
					newRow.put(ThothDB.col_T_C_CONTACTNAME, T_C_CONTACTNAME);
					newRow.put(ThothDB.col_T_C_DATETIME, T_C_DATETIME);
					newRow.put(ThothDB.col_T_C_DURATION, T_C_DURATION);
					newRow.put(ThothDB.col_T_C_TYPE, T_C_TYPE);
					try
					{
						db.insertOrThrow(ThothDB.table_TEMP_CALL, "", newRow);
					}
					catch (SQLException e)
					{
						// ThothLog.e(e);
					}
					callCur.moveToNext();
				}
				if (db.isOpen())
					db.close();
				callCur.close();
				Thoth.Settings.APP_LAST_CALL_CAPTURE = System.currentTimeMillis();
				Thoth.Settings.write();
			}
		});
	}
	
	void missedSMSCapture()
	{
		service.submit(new Runnable()
		{
			@Override
			public void run()
			{
				float T_M_DATETIME;
				String H_M_PKEY;
				String T_M_NUMBER, T_M_CONTACT, T_M_CONTACTNAME, T_M_MSG, T_M_TYPE;
				ContentResolver cr = getContentResolver();
				Cursor smsCur = cr.query(Uri.parse("content://sms"), null, null, null, null);
				if (!smsCur.moveToFirst())
					return;
				ThothDB dbA = new ThothDB(cx);
				dbA.open();
				SQLiteDatabase db = dbA.getDb();
				for (int i = 0; i < 100 && i < smsCur.getCount(); i++)
				{
					T_M_NUMBER = smsCur.getString(smsCur.getColumnIndexOrThrow("address")).toString();
					T_M_CONTACT = T_M_NUMBER;
					T_M_CONTACTNAME = "UNKNOWN";
					T_M_DATETIME = smsCur.getFloat(smsCur.getColumnIndexOrThrow("date"));
					T_M_MSG = smsCur.getString(smsCur.getColumnIndexOrThrow("body")).toString();
					T_M_TYPE = smsCur.getString(smsCur.getColumnIndexOrThrow("type")).toString();
					if (Integer.parseInt(T_M_TYPE) == 1 || Integer.parseInt(T_M_TYPE) == 2)
					{
						T_M_TYPE = (Integer.parseInt(T_M_TYPE) == 1) ? "0" : "1";
						H_M_PKEY = MD5.getMD5HEX(T_M_NUMBER + T_M_CONTACT + T_M_DATETIME + T_M_MSG + T_M_TYPE);
						// Write to DB.
						// Insert HASH in h_Msgs
						ContentValues newRow = new ContentValues();
						newRow.put(ThothDB.col_H_M_PKEY, H_M_PKEY);
						try
						{
							db.insertOrThrow(ThothDB.table_HASH_MSGS, "", newRow);
						}
						catch (SQLException exp)
						{
							// ThothLog.e(e);
							if (smsCur.moveToNext())
								continue;
							else
								break;
						}
						// Insert record into t_Msgs
						newRow = new ContentValues();
						newRow.put(ThothDB.col_T_M_FKEY, H_M_PKEY);
						newRow.put(ThothDB.col_T_M_NUMBER, T_M_NUMBER);
						Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(T_M_NUMBER));
						Cursor c = null;
						try
						{
							c = cr.query(uri, new String[]{PhoneLookup.LOOKUP_KEY, PhoneLookup.DISPLAY_NAME}, null, null, null);
							if (null != c && c.moveToFirst())
							{
								T_M_CONTACT = c.getString(0);
								T_M_CONTACTNAME = c.getString(1);
							}
						}
						catch (Exception e)
						{}
						finally
						{
							if (null != c)
								c.close();
						}
						newRow.put(ThothDB.col_T_M_CONTACT, T_M_CONTACT);
						newRow.put(ThothDB.col_T_M_CONTACTNAME, T_M_CONTACTNAME);
						newRow.put(ThothDB.col_T_M_DATETIME, T_M_DATETIME);
						newRow.put(ThothDB.col_T_M_MSG, T_M_MSG);
						newRow.put(ThothDB.col_T_M_TYPE, T_M_TYPE);
						newRow.putNull(ThothDB.col_T_M_BLOB_TEXT);
						newRow.putNull(ThothDB.col_T_M_BLOB_DATA);
						newRow.putNull(ThothDB.col_T_M_BLOB_DATA_MIME);
						try
						{
							db.insertOrThrow(ThothDB.table_TEMP_MSGS, "", newRow);
						}
						catch (SQLException e)
						{
							// ThothLog.e(e);
						}
						catch (Exception e)
						{
							// ThothLog.e(e);
						}
						smsCur.moveToNext();
					}
					else
					{
						smsCur.moveToNext();
						continue;
					}
				}
				if (db.isOpen())
					db.close();
				smsCur.close();
				Thoth.Settings.APP_LAST_MSGS_CAPTURE = System.currentTimeMillis();
				Thoth.Settings.write();
			}
		});
	}
	
	void missedMMSCapture()
	{
		service.submit(new Runnable()
		{
			@Override
			public void run()
			{
				handleMMSCapture(true);
			};
		});
	}
	
	byte[] readMMSPart(String partId)
	{
		byte[] partData = null;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		InputStream is = null;
		try
		{
			ContentResolver mContentResolver = getContentResolver();
			is = mContentResolver.openInputStream(Uri.parse("content://mms/part/" + partId));
			byte[] buffer = new byte[256];
			int len = is.read(buffer);
			while (len >= 0)
			{
				baos.write(buffer, 0, len);
				len = is.read(buffer);
			}
			partData = baos.toByteArray();
		}
		catch (IOException e)
		{}
		finally
		{
			if (is != null)
			{
				try
				{
					is.close();
				}
				catch (IOException e)
				{
					// ThothLog.e(e);
				}
			}
		}
		return partData;
	}
}
